package com.itheima.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.itheima.common.ThreadLocalUtil;
import com.itheima.mapper.CategoryMapper;
import com.itheima.mapper.DishMapper;
import com.itheima.mapper.FlavorsMapper;
import com.itheima.mapper.SetmealDishesMapper;
import com.itheima.pojo.Category;
import com.itheima.pojo.Dish;
import com.itheima.pojo.Flavors;
import com.itheima.pojo.SetmealDishes;
import com.itheima.service.DishService;

import com.itheima.vo.DishVo;
import com.itheima.vo.PagingQueryVo;
import com.itheima.vo.UserDishVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author :WuJunJie
 * packageName :com.itheima.service.impl
 * fileName :DishServiceImpl
 * creationTime :2022-11-23 13:57
 */

@Service
@Slf4j
public class DishServiceImpl implements DishService {
    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private FlavorsMapper flavorsMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private SetmealDishesMapper setmealDishesMapper;

    @Transactional
    @Override
    public Boolean insertDish(DishVo dishVo) {
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishVo, dish);
        dish.setId(IdUtil.getSnowflakeNextIdStr());
        dish.setCreateTime(LocalDateTime.now());
        dish.setUpdateTime(LocalDateTime.now());
        dish.setCreateUser(ThreadLocalUtil.getid());
        dish.setUpdateUser(ThreadLocalUtil.getid());
        Integer insert = dishMapper.insertDish(dish);
        Integer insert2;
        List<Flavors> flavors = dishVo.getFlavors();
        if (flavors.size() == 0) {
            return insert > 0;
        }
        beforeDishFlavorsInsert(dish, flavors);
        insert2 = flavorsMapper.insertListFlavors(flavors);
        return insert > 0 && insert2 > 0;
    }

    private static void beforeDishFlavorsInsert(Dish dish, List<Flavors> flavors) {
        for (Flavors flavor : flavors) {
            flavor.setId(IdUtil.getSnowflakeNextIdStr());
            flavor.setDishId(dish.getId());
            flavor.setCreateTime(LocalDateTime.now());
            flavor.setUpdateTime(LocalDateTime.now());
            flavor.setCreateUser(ThreadLocalUtil.getid());
            flavor.setUpdateUser(ThreadLocalUtil.getid());
        }
    }

    @Transactional
    @Override
    public Boolean deleteDish(List<String> ids) {

        List<SetmealDishes> setmealDishes = setmealDishesMapper.selectByDishIds(ids);
        if (!setmealDishes.isEmpty()) {
            return false;
        }
        Integer deleteflavors = flavorsMapper.deleteFlavorsByDishIds(ids);
        Integer delete = dishMapper.deleteDish(ids);
        return delete > 0 && deleteflavors > 0;
    }

    @Override
    @Transactional
    public Boolean updateDish(DishVo dishVo) {
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishVo, dish);
        dish.setUpdateTime(LocalDateTime.now());
        dish.setUpdateUser(ThreadLocalUtil.getid());
        Integer update = dishMapper.updateDish(dish);
        flavorsMapper.deleteFlavorsByDishId(dishVo.getId());
        List<Flavors> flavors = dishVo.getFlavors();
        if (flavors.size() == 0) {
            return update > 0;
        }
        beforeDishFlavorsInsert(dish, flavors);
        Integer insertFlavors = flavorsMapper.insertListFlavors(flavors);
        return update > 0 && insertFlavors > 0;
    }

    @Override
    public Boolean changeStatus(Integer status, List<String> ids) {
        LocalDateTime updateTime = LocalDateTime.now();
        String updateUser = ThreadLocalUtil.getid();
        Integer change = dishMapper.changeStatus(status, ids, updateTime, updateUser);
        return change > 0;
    }

    @Override
    public DishVo selectById(String id) {
        Dish dish = dishMapper.selectById(id);
        List<Flavors> flavors = flavorsMapper.selectBydishId(dish.getId());
        DishVo dishVo = new DishVo();
        BeanUtils.copyProperties(dish, dishVo);
        Category category = categoryMapper.selectByCategoryId(dishVo.getCategoryId());
        dishVo.setCategoryName(category.getName());
        dishVo.setFlavors(flavors);
        return dishVo;
    }

    @Override
    public UserDishVo selectByDishId(String id) {
        DishVo dishVo = selectById(id);
        UserDishVo userDishVo = new UserDishVo();
        BeanUtils.copyProperties(dishVo, userDishVo);
        Category category = categoryMapper.selectByCategoryId(dishVo.getCategoryId());
        userDishVo.setType(category.getType());
        userDishVo.setSort(category.getSort());
        return userDishVo;
    }

    @Override
    public PagingQueryVo<Dish> selectPage(String name, Integer page, Integer pageSize) {
        Integer start = (page - 1) * pageSize;
        List<Dish> dishes = dishMapper.selectPage(name, start, pageSize);

        Set<String> ids = dishes.stream().map(Dish::getCategoryId).collect(Collectors.toSet());
        List<Category> categories=categoryMapper.selectByCategoryIds(ids);
        Map<String, List<Category>> categoryMap = categories.stream().collect(Collectors.groupingBy(Category::getId));
        for (Dish dish : dishes) {
            dish.setCategoryName(categoryMap.get(dish.getCategoryId()).get(0).getName());
        }
        PagingQueryVo<Dish> pagingQueryVo = new PagingQueryVo<>();
        pagingQueryVo.setRecords(dishes);
        pagingQueryVo.setSize(pageSize);
        pagingQueryVo.setCurrent(page);
        pagingQueryVo.setTotal(dishMapper.countTotal(name));
        return pagingQueryVo;
    }

    @Override
    public List<DishVo> selectByCategoryId(String categoryId) {
        List<Dish> dishes = dishMapper.selectByCategoryId(categoryId);
        List<DishVo> dishVos = BeanUtil.copyToList(dishes, DishVo.class);
        Set<String> dishIds = dishes.stream().map(Dish::getId).collect(Collectors.toSet());
        List<Flavors> flavors = flavorsMapper.selectBydishIds(dishIds);
        Map<String, List<Flavors>> flavorsMap = flavors.stream().collect(Collectors.groupingBy(Flavors::getDishId));
        Set<String> categoryIds = dishes.stream().map(Dish::getCategoryId).collect(Collectors.toSet());
        List<Category> categories = categoryMapper.selectByCategoryIds(categoryIds);
        Map<String, List<Category>> categoriesMap = categories.stream().collect(Collectors.groupingBy(Category::getId));

        for (DishVo dishVo : dishVos) {
            dishVo.setFlavors(flavorsMap.get(dishVo.getId()));
            dishVo.setCategoryName(categoriesMap.get(dishVo.getCategoryId()).get(0).getName());
        }
        return dishVos;
    }

    @Override
    public List<UserDishVo> selectDishes(String categoryId, Integer status) {
        // 查询所有菜品
        List<Dish> dishes = dishMapper.selectByCategoryIdAndStatus(categoryId, status);
        // 批量copy
        List<UserDishVo> userDishVos = BeanUtil.copyToList(dishes, UserDishVo.class);
        // 把所有查询到的菜品id拿出来   10
        Set<String> dishIds = dishes.stream().map(Dish::getId).collect(Collectors.toSet());
        // 查询这些菜品的口味 10
        List<Flavors> flavorsList = flavorsMapper.selectBydishIds(dishIds);
        // 菜品对相应口味的list 10
        //内有BUG自己找    concurrentHashMap
        Map<String, List<Flavors>> map = flavorsList.stream().collect(Collectors.groupingBy(Flavors::getDishId));
        for (UserDishVo dishVo : userDishVos) {
            List<Flavors> flavorsList1 = map.get(dishVo.getId());
            dishVo.setFlavors(flavorsList1);
        }
        return userDishVos;
    }

    @Override
    public List<UserDishVo> selectByDishIds(Set<String> dishIds) {
        List<Dish> dishes=dishMapper.selectByids(dishIds);
        List<UserDishVo> userDishVos = BeanUtil.copyToList(dishes, UserDishVo.class);
        List<Flavors> flavorsList = flavorsMapper.selectBydishIds(dishIds);
        Map<String, List<Flavors>> flavorsMap = flavorsList.stream().collect(Collectors.groupingBy(Flavors::getDishId));

        for (UserDishVo userDishVo : userDishVos) {
            userDishVo.setFlavors(flavorsMap.get(userDishVo.getId()));
        }
        return userDishVos;
    }


}
